package com.xs.tool.bean;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

public class BeanUtil {
    @SneakyThrows
    public static <T> T toBean(Map<String, Object> map, Class<T> clazz){
        T instance = clazz.getDeclaredConstructor().newInstance();

        for (Map.Entry<String, Object> entry : map.entrySet()) {
            String fieldName = entry.getKey();
            Object value = entry.getValue();

            try {
                Field field = clazz.getDeclaredField(fieldName);
                field.setAccessible(true);
                field.set(instance, value);
            } catch (NoSuchFieldException e) {
                // 字段不存在，跳过
            }
        }
        return instance;
    }

    /**
     * 获取 addValue 对象中与 po 对象相同字段的不同值，并将这些值保留到新的对象实例中
     *
     * @param clazz 类型信息，用于创建新实例
     * @param po    原始对象
     * @param update 更新对象
     * @param <T>   泛型类型
     * @return 包含 addValue 中不同字段值的新实例
     * @throws Exception 如果实例化或反射操作失败
     */
    public static <T> T obtainUpdateBean(Class<T> clazz, T po, T update) throws Exception {
        return obtainUpdateBean(clazz, po, update,null);
    }
    public static <T> T obtainUpdateBean(Class<T> clazz, T po, T update, Class<?> ignoreClass){

        try {
            T instance = clazz.getDeclaredConstructor().newInstance();

            // 遍历所有字段
            for (Field field : po.getClass().getDeclaredFields()) {
                if (ignoreClass != null) {
                    // 如果字段存在忽略注解则跳过
                    if (field.isAnnotationPresent(ignoreClass.asSubclass(java.lang.annotation.Annotation.class))) {
                        continue;
                    }
                }

                field.setAccessible(true);

                Object poValue = field.get(po);
                Object updateValue = field.get(update);

                // 如果值不同，则使用 addValue 的值
                // 这里比较json值
                if (updateValue == null) {
                    continue;
                }

                if (JSON.toJSONString(poValue).equals(JSON.toJSONString(updateValue))) {
                    field.set(instance, updateValue);
                }
            }
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static <T> String obtainUpdateJson(T po, T update){
        if (po == null || update == null || po.getClass() != update.getClass()) {
            throw new RuntimeException("po 和 addValue 类型不一致或为空");
        }
        JSONObject poJO = JSONObject.parseObject(JSONObject.toJSONString(po));
        JSONObject updateJO = JSONObject.parseObject(JSONObject.toJSONString(update));
        JSONObject diff = new JSONObject();

        for (String key : updateJO.keySet()) {
            Object poValue = poJO.get(key);
            Object updateValue = updateJO.get(key);
            // 只保留变动且不为null的字段
            if (updateValue != null && !updateValue.equals(poValue)) {
                diff.put(key, updateValue);
            }
        }
        return diff.toJSONString();
    }




    public static <T> T obtainUpdateBean(T po, T update){
        if (po == null || update == null || po.getClass() != update.getClass()) {
            throw new RuntimeException("po 和 addValue 类型不一致或为空");
        }
        @SuppressWarnings("unchecked")
        Class<T> aClass = (Class<T>) po.getClass();
        try {
            return obtainUpdateBean(aClass, po, update);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


}
